#include "../pch.h"
#include "core/REFNameTable.h"

namespace BFX
{

REFXMLEntityReference::REFXMLEntityReference(const UniString& strName, REFXMLDocument* pDoc)
	: REFXMLLinkedNode(pDoc)
{
	// TODO: if (pDoc->IsLoading())

	m_pLastChild = NULL;
	m_strName = pDoc->GetNameTable()->Add(strName);
}

REFXMLEntityReference::~REFXMLEntityReference()
{
}

// Gets the name of the node.
UniString REFXMLEntityReference::GetName() const
{
	return m_strName;
}

// Gets the name of the node without the namespace prefix.
UniString REFXMLEntityReference::GetLocalName() const
{
	return m_strName;
}

// Gets or sets the value of the node.
UniString REFXMLEntityReference::GetValue() const
{
	return UniString();
}
void REFXMLEntityReference::SetValue(const UniString& strValue)
{
	BFX_ENSURE1(false, "'EntityReference' nodes have no support for setting value.");
}

// Gets the type of the node.
XMLNodeType REFXMLEntityReference::GetNodeType() const
{
	return XMLNodeType_EntityReference;
}

// Saves the node to the specified XmlWriter.
void REFXMLEntityReference::WriteTo(REFXMLWriter* w) const
{
	w->WriteEntityRef(m_strName);
}
// Saves all the children of the node to the specified XmlWriter.
void REFXMLEntityReference::WriteContentTo(REFXMLWriter* w) const
{
	for (REFXMLNode* pNode = GetFirstChild(); pNode != NULL; pNode = pNode->GetNextSibling())
	{
		pNode->WriteTo(w);
	}
}

UniString REFXMLEntityReference::GetBaseURI() const
{
	return GetOwnerDocument()->GetBaseURI();
}

bool REFXMLEntityReference::IsContainer() const
{
	return true;
}

void REFXMLEntityReference::SetParent(REFXMLNode* pNode)
{
	REFXMLLinkedNode::SetParent(pNode);
	if (GetFirstNode() == NULL && pNode != NULL && pNode != GetOwnerDocument())
	{
		// first time insert the entity reference into the tree, we should expand its children now

		// TODO: REF<REFXMLLoader> pLoader = new REFXMLLoader();
		// TODO: pLoader->ExpandEntityReference(this);
	}
}
void REFXMLEntityReference::SetParentForLoad(REFXMLNode* pNode)
{
	SetParent(pNode);
}

REFXMLLinkedNode* REFXMLEntityReference::GetFirstNode() const
{
	return m_pFirstChild;
}
void REFXMLEntityReference::SetFirstNode(REFXMLLinkedNode* pFirstNode)
{
	m_pFirstChild = pFirstNode;
}

REFXMLLinkedNode* REFXMLEntityReference::GetLastNode() const
{
	return m_pLastChild;
}
void REFXMLEntityReference::SetLastNode(REFXMLLinkedNode* pLastChild)
{
	m_pLastChild = pLastChild;
}

bool REFXMLEntityReference::IsValidChildType(XMLNodeType type) const
{
	switch (type)
	{
	case XMLNodeType_Element:
	case XMLNodeType_Text:
	case XMLNodeType_EntityReference:
	case XMLNodeType_Comment:
	case XMLNodeType_Whitespace:
	case XMLNodeType_SignificantWhitespace:
	case XMLNodeType_ProcessingInstruction:
	case XMLNodeType_CDATA:
		return true;
	default:
		return false;
	}
}

// Returns where the entity reference node's children come from
UniString REFXMLEntityReference::GetChildBaseURI() const
{
	//get the associate entity and return its baseUri
	REFXMLEntity* pEnt = GetOwnerDocument()->GetEntityNode(m_strName);
	if (pEnt != NULL)
	{
		if (!pEnt->GetSystemId().IsEmpty())
			return ConstructBaseURI(pEnt->GetBaseURI(), pEnt->GetSystemId()); 
		else
			return pEnt->GetBaseURI();
	}
	return UniString();	// Empty
}

UniString REFXMLEntityReference::ConstructBaseURI(const UniString& strBaseURI, const UniString& strSystemId) const
{
	if (strBaseURI.IsEmpty())
		return strSystemId;
	int nCount = strBaseURI.LastIndexOf('/') + 1;
	UniString strBuf = strBaseURI;
	if (nCount > 0 && nCount < strBaseURI.GetLength())
		strBuf = strBaseURI.Substring(0, nCount);
	else if ( nCount == 0 )
		strBuf += '\\';
	return (strBuf + strSystemId.Replace('\\', '/'));
}

}	//	namespace BFX
